﻿using System;

public class BlipBuffer
{
    internal int dc_acc;
    internal int dc_diff;
    internal int dc_prev;
    public int[] diff;
    public int[][] imp;
    internal int lastChanged;
    internal int prevSum;
    public int sinc_periods;
    public int smp_period;
    public int win_size;

    public virtual void clear()
    {
        for (int i = 0; i < this.diff.Length; i++)
        {
            this.diff[i] = 0;
        }
        this.lastChanged = 0;
    }

    public virtual void impulse(int smpPos, int smpOffset, int magnitude)
    {
        for (int i = this.lastChanged; i < (smpPos + this.win_size); i++)
        {
            this.diff[i] = this.prevSum;
        }
        for (int j = 0; j < this.win_size; j++)
        {
            this.diff[smpPos + j] += (this.imp[smpOffset][j] * magnitude) >> 8;
        }
        this.lastChanged = smpPos + this.win_size;
        this.prevSum = this.diff[(smpPos + this.win_size) - 1];
    }

    public virtual void init(int bufferSize, int windowSize, int samplePeriod, int sincPeriods)
    {
        this.win_size = windowSize;
        this.smp_period = samplePeriod;
        this.sinc_periods = sincPeriods;
        double[] numArray = new double[this.smp_period * this.win_size];
        double num = this.sinc_periods;
        for (int i = 0; i < numArray.Length; i++)
        {
            numArray[i] = sinc((-num * 3.1415926535897931) + ((((num * 2.0) * i) * 3.1415926535897931) / ((double) numArray.Length)));
        }
        this.imp = new int[this.smp_period][];
        for (int j = 0; j < this.smp_period; j++)
        {
            this.imp[j] = new int[this.win_size];
        }
        for (int k = 0; k < this.smp_period; k++)
        {
            double num5 = 0.0;
            for (int m = 0; m < this.win_size; m++)
            {
                num5 += 32768.0 * numArray[(m * this.smp_period) + k];
                this.imp[(this.smp_period - 1) - k][m] = (int) num5;
            }
        }
        this.diff = new int[bufferSize];
        this.lastChanged = 0;
        this.prevSum = 0;
        this.dc_prev = 0;
        this.dc_diff = 0;
        this.dc_acc = 0;
    }

    public virtual int integrate()
    {
        int prevSum = this.prevSum;
        for (int i = 0; i < this.diff.Length; i++)
        {
            prevSum += this.diff[i];
            this.dc_diff = prevSum - this.dc_prev;
            this.dc_prev += this.dc_diff;
            this.dc_acc += this.dc_diff - (this.dc_acc >> 10);
            this.diff[i] = this.dc_acc;
        }
        this.prevSum = prevSum;
        return this.lastChanged;
    }

    public static double sinc(double x)
    {
        if (x == 0.0)
        {
            return 1.0;
        }
        return (Math.Sin(x) / x);
    }
}

